from rest_framework import serializers
from .models import Order, OrderDetail
from course.models import Course
from rest_framework.exceptions import APIException
import uuid
from django.conf import settings
from libs.ali_pay import alipay, GATEWAY


class OrderPaySerializer(serializers.ModelSerializer):
    courses = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all(), many=True)

    class Meta:
        model = Order
        fields = [
            'courses',
            'total_amount',
            'subject',
            'pay_type'
        ]

    def _check_total_amount(self, attrs):
        # 判断前端的价格是否合法，是否与订单中的内容一直
        courses = attrs.get('courses')
        total_amount = attrs.get('total_amount')
        real_total_amount = sum([course.price for course in courses])
        assert real_total_amount == total_amount, APIException('价格不合法')
        return total_amount

    def _get_out_trade_no(self):
        # 使用uuid生成订单号
        # 将uuid中键的【-】去除
        out_trade_no = str(uuid.uuid4()).replace('-', '')
        return out_trade_no

    def _get_user(self):
        return self.context.get('user')

    def _get_pay_url(self, out_trade_no, total_amount, subject):
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=float(total_amount),  # 只有生成支付宝链接时，不能用Decimal
            subject=subject,
            return_url=settings.RETURN_URL,  # get 回调 --》前端
            notify_url=settings.NOTIFY_URL,  # post 回调--》后端
        )
        pay_url = GATEWAY + '?' + order_string
        # 将支付链接存入，传递给views
        self.context['pay_url'] = pay_url

    def _before_create(self, attrs, user, out_trade_no):
        '''
        构建订单数据
        :param attrs: {'courses':[对象,],'total_amount':0.1,'subject':课程名,'pay_type':1}
        :param user: 下单用户
        :param out_trade_no:订单号
        :return:
        '''
        attrs['user'] = user
        attrs['out_trade_no'] = out_trade_no

    def validate(self, attrs):
        # 比较价格是否正确
        total_amount = self._check_total_amount(attrs)
        # 生成订单号
        out_trade_no = self._get_out_trade_no()
        # 3 当前登录用户
        user = self._get_user()
        # 4 获取支付链接
        self._get_pay_url(out_trade_no, total_amount, attrs.get('subject'))
        # 5 入库(两个表)的信息准备
        self._before_create(attrs, user, out_trade_no)
        return attrs

    def create(self, validated_data):
        # 将课程对象弹出，因为要放在orderdetail中
        courses = validated_data.pop('courses')
        # 其他数据都是order表的数据了
        order = Order.objects.create(**validated_data)
        for course in courses:
            OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)
        return order


class ListTestOrderPaySerializer(serializers.ModelSerializer):
    # [1,3,5]
    courses = serializers.ListField()

    class Meta:
        model = Order
        fields = [
            'courses',
            'total_amount',
            'subject',
            'pay_type'
        ]

    def _check_total_amount(self, attrs):
        # 判断前端的价格是否合法，是否与订单中的内容一直
        courses = attrs.get('courses')
        total_amount = attrs.get('total_amount')
        real_total_amount = sum([course.price for course in courses])
        assert real_total_amount == total_amount, APIException('价格不合法')
        return total_amount

    def _get_out_trade_no(self):
        # 使用uuid生成订单号
        # 将uuid中键的【-】去除
        out_trade_no = str(uuid.uuid4()).replace('-', '')
        return out_trade_no

    def _get_user(self):
        return self.context.get('user')

    def _get_pay_url(self, out_trade_no, total_amount, subject):
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=float(total_amount),  # 只有生成支付宝链接时，不能用Decimal
            subject=subject,
            return_url=settings.RETURN_URL,  # get 回调 --》前端
            notify_url=settings.NOTIFY_URL,  # post 回调--》后端
        )
        pay_url = GATEWAY + '?' + order_string
        # 将支付链接存入，传递给views
        self.context['pay_url'] = pay_url

    def _before_create(self, attrs, user, out_trade_no):
        '''
        构建订单数据
        :param attrs: {'courses':[对象,],'total_amount':0.1,'subject':课程名,'pay_type':1}
        :param user: 下单用户
        :param out_trade_no:订单号
        :return:
        '''
        attrs['user'] = user
        attrs['out_trade_no'] = out_trade_no

    def validate(self, attrs):
        # 比较价格是否正确
        total_amount = self._check_total_amount(attrs)
        # 生成订单号
        out_trade_no = self._get_out_trade_no()
        # 3 当前登录用户
        user = self._get_user()
        # 4 获取支付链接
        self._get_pay_url(out_trade_no, total_amount, attrs.get('subject'))
        # 5 入库(两个表)的信息准备
        self._before_create(attrs, user, out_trade_no)
        return attrs

    def create(self, validated_data):
        # 将课程对象弹出，因为要放在orderdetail中
        courses = validated_data.pop('courses')
        # 其他数据都是order表的数据了
        order = Order.objects.create(**validated_data)
        for course in courses:
            OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)
        return order
